package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"time"
)

/** 成员属性结构体 暂时只用于参考 */
type member struct {
	sid            string
	gid            string
	gname          string
	sname          string
	fname          string
	pinyin         string
	abbr           string
	tid            string
	pname          string
	nickname       string
	company        string
	join_day       string
	height         string
	birth_day      string
	star_sign_12   string
	star_sign_48   string
	birth_place    string
	speciality     string
	hobby          string
	experience     string
	catch_phrase   string
	weibo_uid      string
	weibo_verifier string
	blood_type     string
	tieba_kw       string
	status         string
	ranking        string
	pocket_id      string
	is_group_new   string
	tcolor         string
	gcolor         string
}

/** 拉取数据切片数组内的类型别名 */
type rowss = []map[string]string

var allMembers = map[string]rowss{}

func main() {

	// 一、拉取成员信息
	memberBytes := queryFromNetwork()
	json.Unmarshal(memberBytes, &allMembers)
	all := allMembers["rows"] // 必须在拉取完成之后
	for {
	A:
		str := ""
		fmt.Println("请输入指令:")
		fmt.Println("1.导出成员json文件.")
		fmt.Println("2.查询成员,输入姓名中的一个字或全称,得到成员姓名+sid.")
		fmt.Println("3.查询成员,输入姓名中拼音,得到成员姓名+sid.")
		fmt.Println("4.查询成员,输入团名英文,得到成员姓名+sid.")
		fmt.Println("5.查询成员,输入成员唯一的sid,得到成员的详细信息.")
		fmt.Println("6.退出.")
		fmt.Scan(&str)
		switch str {
		case "1":
			writeToFile("members.json", memberBytes)
			goto A
		case "2":
			queryTemple(all, "请输入成员姓名(任意一个字):", "sname", "sname", "sid")
			goto A
		case "3":
			queryTemple(all, "请输入成员拼音全称(如段艺璇就输入duanyixuan或者duan等):", "pinyin", "sname", "sid")
			goto A
		case "4":
			queryTemple(all, "请输入团名(不包含48如snh、bej、gnz、cgt、ckg):", "gname", "sname", "sid")
			goto A
		case "5":
			arrs := queryTemple(all, "请输入sid查询成员详细信息:", "sid")
			if len(arrs) > 0 {
				fmt.Println("是否查看该成员微博? yes/no")
				var inputStr string = ""
				fmt.Scan(&inputStr)
				if inputStr == "yes" {
					url := "https://weibo.com/u/" + arrs[0]["weibo_uid"]
					OpenBrowser(url)
				}
			}
			goto A
		case "6":
			goto B
		default:
			fmt.Println("提示: 对不起您输入的指令有误请重新输入!")
			goto A
		}
	}
B:
	return
}

/**
* 从h5.48.cn拉取成员信息,并写入json
* 返回字节切片
 */
func queryFromNetwork() []byte {
	fmt.Println("**** 欢迎使用snh48成员查询工具! by Goog、2025 ****")
	fmt.Println("提示: 正在拉取成员名单...")
	timestamp := time.Now().Unix()
	url := "https://h5.48.cn/resource/jsonp/allmembers.php?gid=00&_=" + string(timestamp)
	res, _ := http.Get(url)
	bytes, _ := io.ReadAll(res.Body)
	var mm map[string]string
	json.Unmarshal(bytes, &mm)
	fmt.Printf("提示: 拉取成员成功! 共计成员%s个! \n", mm["total"])
	return bytes
}

func writeToFile(fileName string, target []byte) bool {
	// str := fileName
	// fmt.Println("请输入文件名:")
	// fmt.Printf("%s\n", str)
	// fmt.Scan(&str)
	tempFile := make(map[string]rowss)
	json.Unmarshal(target, &tempFile)
	jjsson, _ := json.Marshal(tempFile)
	file, err := os.OpenFile(fileName, os.O_CREATE|os.O_RDONLY, 0644)
	file.Write(jjsson)
	defer file.Close()
	if err != nil {
		return false
	}
	fmt.Println("提示: 写出文件members.json成功!")
	return true
}

/**
* queryTemple
* meta 查询结构元数据
* notice 提示语
* property 搜索属性
* showProperties 展示属性
 */
func queryTemple(meta rowss, notice string, propertyName string, showProperties ...string) rowss {
	//打印提示语 如请输入xxx
	fmt.Println(notice)
	str := ""
	fmt.Scan(&str)
	temp := rowss{}
	for i := 0; i < len(meta); i++ {
		// 属性值自动转小写 并去掉空格
		if strings.Contains(strings.ToLower(strings.ReplaceAll(meta[i][propertyName], " ", "")), str) {

			tem := map[string]string{} // 定义一个map类型来接收自定义属性

			if len(showProperties) == 0 {
				// 没有传入具体取哪些属性就返回全部属性
				tem = meta[i]
				for v := range meta[i] {
					fmt.Printf("%s:%s \n", v, meta[i][v])
				}
			} else {
				for _, v := range showProperties {
					tem[v] = meta[i][v]
					fmt.Printf("%s:%s ", v, meta[i][v])
				}
				fmt.Println("")
			}

			temp = append(temp, tem)
		}
	}

	// 如果查询结果为空请告诉用户
	if len(temp) == 0 {
		fmt.Println("没有查询到任何信息!")
	}
	return temp
}

/** 打开浏览器 */
func OpenBrowser(url string) {
	var cmd *exec.Cmd

	switch os := runtime.GOOS; os {
	case "windows":
		cmd = exec.Command("rundll32", "url.dll,FileProtocolHandler", url)
	case "darwin":
		cmd = exec.Command("open", url)
	case "linux":
		// Linux has multiple ways to open a browser, this is just one example
		// and might not work for all Linux distributions/desktop environments
		cmd = exec.Command("xdg-open", url)
	default:
		log.Printf("Unsupported operating system: %s", os)
		return
	}

	// If no URL is provided, some commands (like "xdg-open") might still work
	// by opening the user's default browser, but others (like "open" on macOS)
	// require a URL. Here, we check if the URL is empty and skip running the command
	// if it is, assuming the user just wants to open the browser without a URL.
	// However, for simplicity and compatibility, we'll always pass the URL,
	// even if it's empty. The command should handle it gracefully.

	err := cmd.Run()
	if err != nil {
		log.Printf("Error opening browser: %v", err)
	}
}
